﻿using System;
using QQ2564874169.Json;

namespace QQ2564874169.RelationalSql.Trigger
{
    public class TriggerPublisher : IWatchBefore
    {
        public event EventHandler<TriggerBeforeArgs> Before;
         
        private IDbExecute _execute;

        public TriggerPublisher(IDbExecute execute)
        {
            _execute = execute;
        }

        protected virtual void OnBefore(TriggerBeforeArgs e)
        {
            Before?.Invoke(this, e);
        }

        protected virtual string Serialize(object obj)
        {
            return JsonHelper.ToJson(obj);
        }

        void IWatchBefore.OnBefore(DbExecuteOperation operation, Type tableType, object model)
        {
            if (tableType == typeof(TriggerItem))
                return;
            if (_execute.InTransaction == false)
                throw new ArgumentException("不在事务中。");

            var before = new TriggerBeforeArgs
            {
                Model = model,
                Operation = operation,
                TableType = tableType
            };
            OnBefore(before);

            if (before.Cancel) return;

            var entityType = tableType.AssemblyQualifiedName;
            var itemModel = model;
            if (model is DbUpdateEventArgs)
            {
                var args = (DbUpdateEventArgs) model;
                itemModel = new UpdateArgs
                {
                    IsSetNull = args.IsSetNull,
                    Sets = args.Sets,
                    Where = args.Where,
                    TableType = entityType
                };
                entityType = typeof(UpdateArgs).AssemblyQualifiedName;
            }
            var item = new TriggerItem
            {
                Id = Guid.NewGuid().ToString().ToLower(),
                Name = tableType.Name,
                Type = operation.ToTriggerType(),
                TableType = tableType.AssemblyQualifiedName,
                EntityType = entityType,
                Entity = Serialize(itemModel),
                CreateTime = DateTime.Now.ToLong(),
                Processed = false,
                State = before.State,
                ProcessTime = 0
            };
            _execute.Insert(item);
        }
    }
}
